@adminforth/markdown 1.10.11 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build.log CHANGED
@@ -14,5 +14,5 @@ custom/tsconfig.json
14
14
  custom/utils/
15
15
  custom/utils/monacoMarkdownToggle.ts
16
16
 
17
- sent 52,817 bytes received 180 bytes 105,994.00 bytes/sec
18
- total size is 52,125 speedup is 0.98
17
+ sent 52,957 bytes received 180 bytes 106,274.00 bytes/sec
18
+ total size is 52,265 speedup is 0.98
@@ -12,6 +12,10 @@
12
12
  prose-hr:my-1
13
13
  leading-tight
14
14
  dark: dark:text-gray-300
15
+ dark:[&_th]:text-white
16
+ dark:[&_td]:text-white
17
+ dark:[&_thead]:border-b-gray-600
18
+ dark:[&_code]:text-white
15
19
  dark:[&_h1]:text-white dark:[&_h2]:text-gray-100 dark:[&_h3]:text-gray-200
16
20
  dark:[&_a]:text-white dark:[&_a:hover]:text-white
17
21
  dark:[&_pre]:bg-black dark:[&_pre]:border dark:[&_border-slate-800]
@@ -12,6 +12,10 @@
12
12
  prose-hr:my-1
13
13
  leading-tight
14
14
  dark: dark:text-gray-300
15
+ dark:[&_th]:text-white
16
+ dark:[&_td]:text-white
17
+ dark:[&_thead]:border-b-gray-600
18
+ dark:[&_code]:text-white
15
19
  dark:[&_h1]:text-white dark:[&_h2]:text-gray-100 dark:[&_h3]:text-gray-200
16
20
  dark:[&_a]:text-white dark:[&_a:hover]:text-white
17
21
  dark:[&_pre]:bg-black dark:[&_pre]:border dark:[&_border-slate-800]
package/dist/index.js CHANGED
@@ -19,11 +19,24 @@ export default class MarkdownPlugin extends AdminForthPlugin {
19
19
  }
20
20
  // Placeholder for future Upload Plugin API integration.
21
21
  // For now, treat all extracted URLs as plugin-owned public URLs.
22
- isPluginPublicUrl(_url) {
23
- // todo: here we need to check that host name is same as upload plugin, probably create upload plugin endpoint
24
- // should handle cases that user might define custom preview url
25
- // and that local storage has no host name, here, the fact of luck of hostname might be used as
26
- return true;
22
+ isUrlFromPlugin(url) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ if (!this.uploadPlugin)
25
+ return false;
26
+ try {
27
+ const uploadPlugin = this.uploadPlugin;
28
+ if (typeof uploadPlugin.isInternalUrl === 'function') {
29
+ return yield uploadPlugin.isInternalUrl(url);
30
+ }
31
+ else {
32
+ throw new Error('Please update upload plugin and storage adapter');
33
+ }
34
+ }
35
+ catch (err) {
36
+ console.error(`[MarkdownPlugin] Error checking URL ${url}:`, err);
37
+ }
38
+ return false;
39
+ });
27
40
  }
28
41
  validateConfigAfterDiscover(adminforth, resourceConfig) {
29
42
  this.adminforth = adminforth;
@@ -150,18 +163,22 @@ export default class MarkdownPlugin extends AdminForthPlugin {
150
163
  };
151
164
  const shouldTrackUrl = (url) => {
152
165
  try {
153
- return this.isPluginPublicUrl(url);
166
+ return this.isUrlFromPlugin(url);
154
167
  }
155
168
  catch (err) {
156
169
  console.error('Error checking URL ownership', url, err);
157
170
  return false;
158
171
  }
159
172
  };
160
- const getKeyFromTrackedUrl = (rawUrl) => {
173
+ const getKeyFromTrackedUrl = (rawUrl) => __awaiter(this, void 0, void 0, function* () {
161
174
  const srcTrimmed = rawUrl.trim().replace(/^<|>$/g, '');
162
175
  if (!srcTrimmed || srcTrimmed.startsWith('data:') || srcTrimmed.startsWith('javascript:')) {
163
176
  return null;
164
177
  }
178
+ const isInternal = yield this.isUrlFromPlugin(srcTrimmed);
179
+ if (!isInternal) {
180
+ return null;
181
+ }
165
182
  if (!shouldTrackUrl(srcTrimmed)) {
166
183
  return null;
167
184
  }
@@ -171,7 +188,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
171
188
  return null;
172
189
  }
173
190
  return decodeURIComponent(key);
174
- };
191
+ });
175
192
  const upsertMeta = (byKey, key, next) => {
176
193
  var _a, _b;
177
194
  const existing = byKey.get(key);
@@ -201,38 +218,40 @@ export default class MarkdownPlugin extends AdminForthPlugin {
201
218
  return cleaned || null;
202
219
  };
203
220
  function getAttachmentMetas(markdown) {
204
- var _a, _b, _c, _d, _e, _f;
205
- if (!markdown) {
206
- return [];
207
- }
208
- // Markdown image syntax: ![alt](src) or ![alt](src "title") or ![alt](src 'title')
209
- const imageRegex = /!\[([^\]]*)\]\(\s*([^\s)]+)\s*(?:\s+(?:\"([^\"]*)\"|'([^']*)'))?\s*\)/g;
210
- // HTML embedded media links.
211
- const htmlSrcRegex = /<(?:source|video)\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s"'=<>`]+))[^>]*>/gi;
212
- const byKey = new Map();
213
- for (const match of markdown.matchAll(imageRegex)) {
214
- const altRaw = (_a = match[1]) !== null && _a !== void 0 ? _a : '';
215
- const srcRaw = match[2];
216
- const titleRaw = normalizeAttachmentTitleForDb((_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null);
217
- const key = getKeyFromTrackedUrl(srcRaw);
218
- if (!key) {
219
- continue;
221
+ return __awaiter(this, void 0, void 0, function* () {
222
+ var _a, _b, _c, _d, _e, _f;
223
+ if (!markdown) {
224
+ return [];
220
225
  }
221
- upsertMeta(byKey, key, {
222
- alt: altRaw,
223
- title: titleRaw,
224
- });
225
- }
226
- let srcMatch;
227
- while ((srcMatch = htmlSrcRegex.exec(markdown)) !== null) {
228
- const srcRaw = (_f = (_e = (_d = srcMatch[1]) !== null && _d !== void 0 ? _d : srcMatch[2]) !== null && _e !== void 0 ? _e : srcMatch[3]) !== null && _f !== void 0 ? _f : '';
229
- const key = getKeyFromTrackedUrl(srcRaw);
230
- if (!key) {
231
- continue;
226
+ // Markdown image syntax: ![alt](src) or ![alt](src "title") or ![alt](src 'title')
227
+ const imageRegex = /!\[([^\]]*)\]\(\s*([^\s)]+)\s*(?:\s+(?:\"([^\"]*)\"|'([^']*)'))?\s*\)/g;
228
+ // HTML embedded media links.
229
+ const htmlSrcRegex = /<(?:source|video)\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s"'=<>`]+))[^>]*>/gi;
230
+ const byKey = new Map();
231
+ for (const match of markdown.matchAll(imageRegex)) {
232
+ const altRaw = (_a = match[1]) !== null && _a !== void 0 ? _a : '';
233
+ const srcRaw = match[2];
234
+ const titleRaw = normalizeAttachmentTitleForDb((_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null);
235
+ const key = yield getKeyFromTrackedUrl(srcRaw);
236
+ if (!key) {
237
+ continue;
238
+ }
239
+ upsertMeta(byKey, key, {
240
+ alt: altRaw,
241
+ title: titleRaw,
242
+ });
232
243
  }
233
- upsertMeta(byKey, key, {});
234
- }
235
- return [...byKey.values()];
244
+ let srcMatch;
245
+ while ((srcMatch = htmlSrcRegex.exec(markdown)) !== null) {
246
+ const srcRaw = (_f = (_e = (_d = srcMatch[1]) !== null && _d !== void 0 ? _d : srcMatch[2]) !== null && _e !== void 0 ? _e : srcMatch[3]) !== null && _f !== void 0 ? _f : '';
247
+ const key = yield getKeyFromTrackedUrl(srcRaw);
248
+ if (!key) {
249
+ continue;
250
+ }
251
+ upsertMeta(byKey, key, {});
252
+ }
253
+ return [...byKey.values()];
254
+ });
236
255
  }
237
256
  const createAttachmentRecords = (adminforth, options, recordId, metas, adminUser) => __awaiter(this, void 0, void 0, function* () {
238
257
  if (!metas.length) {
@@ -334,7 +353,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
334
353
  });
335
354
  (resourceConfig.hooks.create.afterSave).push((_a) => __awaiter(this, [_a], void 0, function* ({ record, adminUser }) {
336
355
  // find all s3Paths in the html
337
- const metas = getAttachmentMetas(record[this.options.fieldName]);
356
+ const metas = yield getAttachmentMetas(record[this.options.fieldName]);
338
357
  const keys = metas.map(m => m.key);
339
358
  process.env.HEAVY_DEBUG && console.log('📸 Found attachment keys', keys);
340
359
  // create attachment records
@@ -355,7 +374,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
355
374
  Filters.EQ(this.options.attachments.attachmentResourceIdFieldName, resourceConfig.resourceId)
356
375
  ]);
357
376
  const existingKeys = existingAparts.map((a) => a[this.options.attachments.attachmentFieldName]);
358
- const metas = getAttachmentMetas(record[this.options.fieldName]);
377
+ const metas = yield getAttachmentMetas(record[this.options.fieldName]);
359
378
  const newKeys = metas.map(m => m.key);
360
379
  process.env.HEAVY_DEBUG && console.log('📸 Existing keys (from db)', existingKeys);
361
380
  process.env.HEAVY_DEBUG && console.log('📸 Found new keys (from text)', newKeys);
package/index.ts CHANGED
@@ -19,11 +19,19 @@ export default class MarkdownPlugin extends AdminForthPlugin {
19
19
 
20
20
  // Placeholder for future Upload Plugin API integration.
21
21
  // For now, treat all extracted URLs as plugin-owned public URLs.
22
- isPluginPublicUrl(_url: string): boolean {
23
- // todo: here we need to check that host name is same as upload plugin, probably create upload plugin endpoint
24
- // should handle cases that user might define custom preview url
25
- // and that local storage has no host name, here, the fact of luck of hostname might be used as
26
- return true;
22
+ async isUrlFromPlugin(url: string): Promise<boolean> {
23
+ if (!this.uploadPlugin) return false;
24
+ try {
25
+ const uploadPlugin = this.uploadPlugin as any;
26
+ if (typeof uploadPlugin.isInternalUrl === 'function') {
27
+ return await uploadPlugin.isInternalUrl(url);
28
+ } else {
29
+ throw new Error ('Please update upload plugin and storage adapter')
30
+ }
31
+ } catch (err) {
32
+ console.error(`[MarkdownPlugin] Error checking URL ${url}:`, err);
33
+ }
34
+ return false;
27
35
  }
28
36
 
29
37
  validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
@@ -168,18 +176,22 @@ export default class MarkdownPlugin extends AdminForthPlugin {
168
176
 
169
177
  const shouldTrackUrl = (url: string) => {
170
178
  try {
171
- return this.isPluginPublicUrl(url);
179
+ return this.isUrlFromPlugin(url);
172
180
  } catch (err) {
173
181
  console.error('Error checking URL ownership', url, err);
174
182
  return false;
175
183
  }
176
184
  };
177
185
 
178
- const getKeyFromTrackedUrl = (rawUrl: string): string | null => {
186
+ const getKeyFromTrackedUrl = async (rawUrl: string): Promise<string | null> => {
179
187
  const srcTrimmed = rawUrl.trim().replace(/^<|>$/g, '');
180
188
  if (!srcTrimmed || srcTrimmed.startsWith('data:') || srcTrimmed.startsWith('javascript:')) {
181
189
  return null;
182
190
  }
191
+ const isInternal = await this.isUrlFromPlugin(srcTrimmed);
192
+ if (!isInternal) {
193
+ return null;
194
+ }
183
195
  if (!shouldTrackUrl(srcTrimmed)) {
184
196
  return null;
185
197
  }
@@ -225,7 +237,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
225
237
  return cleaned || null;
226
238
  };
227
239
 
228
- function getAttachmentMetas(markdown: string): AttachmentMeta[] {
240
+ async function getAttachmentMetas(markdown: string): Promise<AttachmentMeta[]> {
229
241
  if (!markdown) {
230
242
  return [];
231
243
  }
@@ -242,7 +254,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
242
254
  const srcRaw = match[2];
243
255
  const titleRaw = normalizeAttachmentTitleForDb((match[3] ?? match[4]) ?? null);
244
256
 
245
- const key = getKeyFromTrackedUrl(srcRaw);
257
+ const key = await getKeyFromTrackedUrl(srcRaw);
246
258
  if (!key) {
247
259
  continue;
248
260
  }
@@ -255,7 +267,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
255
267
  let srcMatch: RegExpExecArray | null;
256
268
  while ((srcMatch = htmlSrcRegex.exec(markdown)) !== null) {
257
269
  const srcRaw = srcMatch[1] ?? srcMatch[2] ?? srcMatch[3] ?? '';
258
- const key = getKeyFromTrackedUrl(srcRaw);
270
+ const key = await getKeyFromTrackedUrl(srcRaw);
259
271
  if (!key) {
260
272
  continue;
261
273
  }
@@ -390,7 +402,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
390
402
 
391
403
  (resourceConfig.hooks.create.afterSave).push(async ({ record, adminUser }: { record: any, adminUser: AdminUser }) => {
392
404
  // find all s3Paths in the html
393
- const metas = getAttachmentMetas(record[this.options.fieldName]);
405
+ const metas = await getAttachmentMetas(record[this.options.fieldName]);
394
406
  const keys = metas.map(m => m.key);
395
407
  process.env.HEAVY_DEBUG && console.log('📸 Found attachment keys', keys);
396
408
  // create attachment records
@@ -416,7 +428,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
416
428
  ]);
417
429
  const existingKeys = existingAparts.map((a: any) => a[this.options.attachments.attachmentFieldName]);
418
430
 
419
- const metas = getAttachmentMetas(record[this.options.fieldName]);
431
+ const metas = await getAttachmentMetas(record[this.options.fieldName]);
420
432
  const newKeys = metas.map(m => m.key);
421
433
 
422
434
  process.env.HEAVY_DEBUG && console.log('📸 Existing keys (from db)', existingKeys)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/markdown",
3
- "version": "1.10.11",
3
+ "version": "1.11.0",
4
4
  "description": "Markdown plugin for adminforth",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",